package mac.filter;
import java.io.*;
import java.net.*;
import java.util.*;
import mac.*;


/** 
 * An <code> Filter </code> object defines a filter which has a list of pointers
 * to monitored variables of a system and observe their values when necessary.
 *
 * @version 1.1
 * @author Moonjoo Kim
 */ 
public class Filter extends Thread
{
    /** A list of monitored objects, methods and fields */

    /** Network-related variables */
    static Socket s = null;
    static int DEFAULT_PORT = 8040;
    static String DEFAULT_HOST = "saul.cis.upenn.edu";
    static DataOutputStream sout;
    static ObjectOutputStream o_out; 
    static Vector buffer = new Vector(100);

    static void setPort(int port) { DEFAULT_PORT = port;}

    /** It initialize communication channel to an event recognizer.  It also
     * generates a filter thread.  A filter thread performs book-keeping of
     * address/name table and actuall communication for making low overhead
     * to original program */
    static public void init(String host, int port) {
	port = port != 0 ? port : DEFAULT_PORT; 
	host = host != null ? host : DEFAULT_HOST; 

	try {
	    s = new Socket(host,port);
	    sout = new DataOutputStream(s.getOutputStream());
	    System.out.println("Connected to " + s.getInetAddress() +
						    ":" + s.getPort());
	    o_out = new ObjectOutputStream(sout);
	}
	catch(IOException e){System.err.println(e);}

	new Filter().start();
    }


    public void run() {
	Object o=null;
	while(true) {
	    if(buffer.size() > 0) {
		o = buffer.elementAt(0);
		Debug.show(o);
		try{ o_out.writeObject(buffer.elementAt(0));}
		catch(IOException e) {System.err.println(e);}
		buffer.removeElementAt(0);
	    }

	    try{ Thread.sleep(100);}
	    catch(InterruptedException e) {System.err.println(e);}
	}
    }

    static public void close() {
	(new SnapshotObj(null,null)).id = "adsf";

	try{ o_out.close();}
	catch(IOException e){System.err.println(e);}
	try{ sout.close();}
	catch(IOException e){System.err.println(e);}
	try{ s.close();}
	catch(IOException e){System.err.println(e);}
    }

    /***************************/
    /* Sending variable update */
    /***************************/

    /** It uses global lock using monitor.  It's declared as synchronized */
    public static synchronized void send(String s,String pc) {
	buffer.addElement(new SnapshotObj(s,pc));
    }
    public static synchronized void send(String s,int i) {
       buffer.addElement(new SnapshotObj(s,new Integer(i)));
    }
    public static synchronized void send(String s,long l) {
       buffer.addElement(new SnapshotObj(s,new Long(l)));
    }
    public static synchronized void send(String s,float f) {
       buffer.addElement(new SnapshotObj(s,new Float(f)));
    }
    public static synchronized void send(String s,double d) {
       buffer.addElement(new SnapshotObj(s,new Double(d)));
    }
    public static synchronized void send(String s,byte by) {
       buffer.addElement(new SnapshotObj(s,new Byte(by)));
    }
    public static synchronized void send(String s,boolean bool) {
       buffer.addElement(new SnapshotObj(s,new Boolean(bool)));
    }
    public static synchronized void send(String s,char c) {
       buffer.addElement(new SnapshotObj(s,new Character(c)));
    }
    public static synchronized void send(String s,short sh) {
       buffer.addElement(new SnapshotObj(s,new Short(sh)));
    }
}
